package com.zyt.springboot.teach_segmentLock;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/*
 * @params: ConcurrentHashMap
 */
public class Demo {
    public static void main(String[] args) {
        Hashtable<Integer,String> hashTable = new Hashtable<>();
        //初始容量16，扩容因子0.75，并发数量16，也就是分成了16段，给每段都加上锁
        ConcurrentHashMap<Integer,String> concurrentHashMap =
                new ConcurrentHashMap<>(16,0.75f,16);
        concurrentHashMap.put(1,"lisi");
        //在jdk1.7之前，concurrentHashMap采用分段锁技术，给每个段上锁，用segment
        //参考源码1370行，segment继承了ReentrantLock，也就是分段锁技术
        //对并发数量进行设置，也就是分了多少段的分段锁
        //这里画个图，对比一下hashTable
        //在jdl1.8之后，node数组+链表+红黑树
        //源码773行，node数组被volatile修饰，保证其可见性，禁止指令重排
        //参考源码1016行，先判断该table是否为空，是空的，进行初始化操作
        //参考源码1019行，对插入的值进行cas操作，来保证插入元素的安全性，先判断下表位置是否为空
        //如果是空就加入，不是空就发展成链表往下放
        //以上操作是为了保证，在某一个为空的下标上，插入数据保证的安全性，
        //也就是该位置还没有发生hash碰撞，用cas保证数据的安全性
        //如果该位置不为空，怎么保证？
        //源码1027行，用synchronized代码块括起来，来保证数据的安全性
        //用hashMap做对比
        HashMap<Integer,String> hashMap = new HashMap<>();
        //源码395行，node数组没有被volatile修饰
        //由此可见HashMap并不是为多线程环境设计的
        //下面我们再来看ConcurrentHashMap中的put()方法
        concurrentHashMap.put(1,"张三");
        hashMap.put(1,"张三");
        //扩展：如何把hashMap集合变成安全的集合？
        Map<Integer, String> integerStringMap = Collections.synchronizedMap(hashMap);
        List<String> list = new ArrayList<>();
        List<String> list1 = Collections.synchronizedList(list);
        System.out.println(integerStringMap);
        //扩展：锁的细粒度
        //简单来说synchronized同步代码块括起来的部分越少，细粒度越高
        //在日常生活中尽量哪里需要上锁再上锁，而不是有一处需要上锁就直接全部锁上
    }

}
